import _ from 'lodash'
import { message } from 'ant-design-vue'
import { ActionTree, MutationTree, Commit } from 'vuex'

import { LoginStatusEnum } from '@/enums/login-status.enum'
import { UserAuth, UserProfile, UserState } from '@/types/user.state'
import { USER_AUTH, USER_PROFILE, USER_STATE_INIT } from '@/enums/mutation-types'
import { BackendResult } from '@/types/backend-result'
import { ResultStatusEnum } from '@/enums/result-status.enum'

const initState: UserState = {
  profile: {
    email: '',
    status: 0,
    mobile: '',
    idUser: '',
    idTenant: '',
    loginName: '',
    realName: '',
    lastLoginTime: ''
  },
  auth: {
    token: '',
    operations: [],
    status: LoginStatusEnum.Logout
  }
}

export const state = () => ({ ...initState })

export const mutations: MutationTree<UserState> = {
  [USER_AUTH] (state, auth: UserAuth) {
    state.auth = auth
  },
  [USER_PROFILE] (state, profile: UserProfile) {
    state.profile = profile
  },
  [USER_STATE_INIT] (state) {
    state.auth = { ...initState.auth }
    state.profile = { ...initState.profile }
  }
}

function commitUserState (commit: Commit, data: any) {
  const profile: UserProfile = {
    idUser: data.idUser,
    idTenant: data.idTenant,
    loginName: data.loginName,
    realName: data.realName,
    email: data.email,
    mobile: data.mobile,
    status: data.status,
    lastLoginTime: data.lastLoginTime
  }
  const auth: UserAuth = {
    token: data.token,
    status: LoginStatusEnum.Login,
    operations: _.compact(_.map(data.operations, 'url'))
  }
  commit(USER_AUTH, auth)
  commit(USER_PROFILE, profile)
}

export const actions: ActionTree<UserState, any> = {
  async authentication ({ commit }, payload): Promise<string|undefined> {
    let errMsg: string|undefined
    const { $resources, $cookies } = this as any
    try {
      const res: BackendResult = await $resources.user.login({
        loginName: payload.loginName,
        password: payload.password
      })
      if (res.status === ResultStatusEnum.SUCCESS) {
        commitUserState(commit, res.data)
        $cookies.set(process.env.cookieToken, (res.data as any).token)
      } else {
        errMsg = res.message
      }
    } catch (e) {
      errMsg = '登录失败，请重试！'
    }
    return errMsg
  },
  async tokenAuthentication ({ commit }): Promise<boolean> {
    let auth = false
    try {
      const res: BackendResult = await (this as any).$resources.user.tokenAuth()
      if (res.status === ResultStatusEnum.SUCCESS) {
        commitUserState(commit, res.data)
        auth = true
      } else if (process.client) {
        message.warning(res.message)
      } else {
        console.log('认证失败:', res.message)
      }
    } catch (e) {
      if (process.client) {
        message.warning('验证用户信息出错！')
      } else {
        console.log('认证出错:', e.message)
      }
    }
    return auth
  },
  clearUserState ({ commit }): void {
    const { $cookies } = this as any
    commit(USER_STATE_INIT)
    $cookies.remove(process.env.cookieToken)
  }
}
